package main

import "fmt"

//panic()  内置函数，抛出异常
//定义如下：func panic(v interface{})
//制造异常
func make_exception() {
	fmt.Println("make exception")
	//抛出异常
	panic("exception a")
	fmt.Println("end make exception") //不会执行（因前面抛出了异常，中断了程序的执行）
}

//recover() 内置函数，获取异常，多次调用，只有第一次能获取值
//定义如下：func recover() interface{}
//捕获异常方法一
func catch_exception_first() {
	fmt.Println("start catch_exception_first")
	err := recover() //获取异常
	if err != nil {
		fmt.Println("dispose first: " + fmt.Sprintf("%s", err))
	}
	fmt.Println("end catch_exception_first")
}

//捕获异常方法二
func catch_exception_second() {
	fmt.Println("start catch_exception_second")
	err := recover() //获取异常
	if err != nil {
		fmt.Println("dispose second: " + fmt.Sprintf("%s", err))
	}
	fmt.Println("end catch exception second")
}

//含有异常的方法
func invoke_exception_test() {
	fmt.Println("start invoke_exception_test")

	//defer 在资源释放、连接关闭、函数结束时调用，多个defer为堆栈结构，先进后出，也就是先进的后执行
	defer catch_exception_first()  //异常处理方法一，根据堆栈原理，先入栈，后执行，异常已经被异常处理方法二捕获，故不能再次捕获异常
	defer catch_exception_second() //异常处理方法二，根据堆栈原理，后入栈，先执行，能捕获异常
	//抛出异常
	make_exception()
	make_exception()                         //不会执行（因前面抛出了异常，中断了程序的执行）
	fmt.Println("end invoke_exception_test") //不会执行（因前面抛出了异常，中断了程序的执行）
}

//普通方法
func normal_method() {
	fmt.Println("start normal_method")
	invoke_exception_test()
	fmt.Println("end normal_method")
}

//main方法
func main() {
	fmt.Println("start main")
	normal_method()
	fmt.Println("end main")
}
